Kubernetes - Configurations
Voir cours architecture avant toutes manipulation, ainsi que les commandes kubectl.
Les configuration de kubernetes sont déclarative, et effectué via des fichiers YAML. La syntaxe est similaire à celle de Docker Compose.
Il faut donc apprendre la structure et comment écrire les fichiers de configuration.
Chaque fichier de configuration à 3 parties obligatoire :
- Les metadata
- names, labels...
- Specification
- Chaque composant aura ses spec, type replicas, selector, ports, template...
- Le kind (Deployment)
- Et les api version
- Chaque sp écification aura ses propres configurations en fonction de son "kind"
- Status
- Automatiquement généré et ajouté par Kubernetes La partie Status va toujours check si le status désiré est différent du status actuel, et va essayer de corriger le status le cas échéant. Par exemple on spécifie 2 replicas, donc kube va ajouter le status au déploiement et va update le state continuellement. Il comparera donc le status avec la config.
Status ?
Ou est stocké le status dans Kubernetes ?
Ces informations viennent de l'ETCD. ( Voir cours) ETCD va stocké les datas du cluster, et contiendra à tout moment les status des éléments de Kubernetes.
webapp.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp-deployment
labels:
app: webapp
spec:
replicas: 1
selector:
matchLabels:
app: webapp
template:
metadata:
labels:
app: webapp
spec:
containers:
- name: webapp
image: nanajanashia/k8s-demo-app:v1.0
ports:
- containerPort: 3000
env:
- name: USER_NAME
valueFrom:
secretKeyRef:
name: mongo-secret
key: mongo-user
- name: USER_PWD
valueFrom:
secretKeyRef:
name: mongo-secret
key: mongo-password
- name: DB_URL
valueFrom:
configMapKeyRef:
name: mongo-config
key: mongo-url
---
apiVersion: v1
kind: Service
metadata:
name: webapp-service
spec:
type: NodePort
selector:
app: webapp
ports:
- protocol: TCP
port: 3000
targetPort: 3000
nodePort: 30100
A la manière de docker, une architecture Kubernetes, dans la bonne pratique, en provisionner avec des fichiers yaml, et non avec les commandes de l'engine directement par exemple.
S'exercer
Installation minikube : https://minikube.sigs.k8s.io/docs/start/ Documentation Kubernetes : https://kubernetes.io/docs/home/ Service : https://kubernetes.io/docs/concepts/services-networking/service/
MongoDB
ConfigMap
mongo-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: mongo-config
data:
mongo-url: mongo-service
data : pair de clefs et valeur défini comme configuration externe, cette valeur sera associé au futur service que nous allons créer.
Mongo Secret
mongo-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: mongo-secret
type: Opaque
data:
mongo-user: bW9uZ291c2Vy
mongo-password: bW9uZ29wYXNzd29yZA==
type : Opaque, type générique
Afin de ne pas stocker les informations en clair, nous pouvons les encoder.
echo -n mongouser | base64
echo -n monpasswd | base64
Maintenant, lorsque nous créerons les Deployment, les configurations pourrons y être référencées.
Deployment et Service MongoDB
Deployments
Nous pouvons écrire toutes les directives dans un seul fichier car les deux vont ensemble. Vous pouvez vous baser sur la documentation.
mongo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: mongo-deployment
labels:
app: mongo
spec:
replicas: 1
selector:
matchLabels:
app: mongo
template:
metadata:
labels:
app: mongo
spec:
containers:
- name: mongodb
image: mongo:5.0
ports:
- containerPort: 27017 # Port par défault de mongo
env:
- name: MONGO_INITDB_ROOT_USERNAME
valueFrom:
secretKeyRef:
name: mongo-secret
key: mongo-user
- name: MONGO_INITDB_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mongo-secret
key: mongo-password
---
apiVersion: v1
kind: Service
metadata:
name: mongo-service
spec:
selector:
app: mongo
ports:
- protocol: TCP
port: 27017 #Port qui sera accessible par l'utilisateur
targetPort: 27017 #Port du pod pour accéder au service
N:b : Kind : Deployment
Une template est une config d'un pod dans la configuration du deployment. En effet, les deployments gèrent les pods. Ils aurons leurs propres metadatas et specifications. Nous définirons à l'intérieur des specs, les images à utiliser, les ports...
Labels: Dans Kubernetes, vous pouvez donner à n'importe quel composant un Label. les labels sont des clefs, des valeurs, attachées à une ressource. Ce sont des identifieurs de composants.
- "release" : "stable"
- "release" : "canary"
- "env" : "dev"
- "env" : "prod"
- "tier" : "frontend"
- "tier" : "backend"
Pourquoi utiliser les labels ?
Les labels sont des éléments clés de Kubernetes. Ils permettent d'identifier et de cibler des composants spécifiques en plus de leur nom. Lorsque plusieurs répliques du même pods sont créées, chaque pods obtient un nom unique, mais elles peuvent partager le même label. Cela permet d'identifier toutes les répliques de la même application en utilisant un label spécifique que tous les pods partagent. C'est pourquoi, dans les métadonnées du pod, nous avons toujours ce label. Pour les pods, les labels sont un champ obligatoire, alors que pour les autres composants tels que le déploiement, ConfigMap, etc., les labels sont facultatifs, mais il est recommandé de les définir.
Lorsque nous créons des répliques de pod, comment le déploiement sait-il quelles parties lui appartiennent ou comment Kubernetes sait-il quels pods appartiennent à quels déploiements ?
Cela est défini en utilisant le sélecteur "matchlabels" dans la spécification du déploiement, qui permet de lier les pods qui ont le même label. Les labels sont libres de choix et peuvent être appelés de n'importe quelle manière, mais il est recommandé d'utiliser la clé "app" pour étiqueter les applications dans Kubernetes. La valeur sera le nom de l'application.
Ensuite, nous devons définir le nombre de répliques de pod que nous voulons créer à l'aide de l'attribut "replicas". Dans notre exemple, nous allons créer une seule réplique car il s'agit d'une base de données.
Services
Maintenant, ajoutons une configuration de service, qui est un élément clé de toute application dans Kubernetes. La configuration de service est beaucoup plus simple que le déploiement. Elle nécessite simplement de définir le nom du service, le sélecteur de label pour lier les pods, et les ports pour accéder à l'application dans le pod.
Il est important de noter que les valeurs de port et de nom peuvent être différentes, mais pour des raisons de simplicité, il est commun de garder ces valeurs identiques. Dans la configuration de mongodb, nous utilisons des secrets et configmaps pour stocker des informations sensibles et pour référencer les variables d'environnement de nos applications.
Dans la majorité des cas, il est important de setup un TargetPort, sur la partie Service, identique au containerPort du Deployment.
Enfin, nous avons configuré notre application web pour se connecter à la base de données en utilisant les variables d'environnement stockées dans un configmap
. Nous avons également modifié la configuration du service pour le rendre accessible de l'extérieur en utilisant un type nodeport
. Enfin, nous avons déployé tous les composants dans Kubernetes en utilisant la commande kubectl apply.
Les services pour MongoDB et l'application web sont présents et le service de l'application web est de type NodePort, ce qui signifie que nous pouvons y accéder de manière externe.
Cependant, nous ne voyons pas ConfigMap et Secret ici, mais nous pouvons les obtenir en utilisant les commandes kubectl get configmap
et kubectl get secret
.
Afficher tous les composants est facile avec la commande 'kubectl get', suivie du nom du composant, comme 'pod', qui affiche une liste des composants avec des données supplémentaires.
La commande 'kubectl' est un outil très puissant avec de nombreuses sous-commandes. Pour avoir une vue d'ensemble et savoir ce que vous pouvez faire avec, vous pouvez utiliser la commande
kubectl help
, qui liste toutes les sous-commandes que vous pouvez utiliser avec elle.
Vous pouvez également obtenir de l'aide pour chaque sous-commande, comme kubectl get
, pour voir tous les exemples et les options disponibles. kubectl get
est évidemment la commande la plus courante que vous allez utiliser pour lister tous les composants.
Si vous voulez voir plus de détails sur un certain composant, vous pouvez utiliser la commande kubectl describe
pour ce composant, comme un service, par exemple, et l'instance réelle de ce composant, comme 'web app service', qui donnera une sortie plus détaillée sur ce composant spécifique.
De même, vous pouvez également utiliser kubectl describe pod
' pour obtenir des détails sur votre pod, y compris le statut de la planification du pod, la configuration du conteneur, les labels, etc.
Si vous avez des applications en cours d'exécution dans votre cluster, vous voudrez vérifier les journaux pour dépanner, déboguer ou vous assurer que tout va bien à l'intérieur du pod.
Vous pouvez le faire très facilement en utilisant la commande 'kubectl logs
en spécifiant simplement le nom du pod, ce qui vous donnera les journaux du conteneur à l'intérieur.
Vous pouvez même diffuser les journaux en utilisant l'option -f
.
Enfin, pour valider que notre application est également accessible depuis le navigateur, nous avons configuré le service et nous pouvons obtenir le service en utilisant la commande 'kubectl get service
ou kubectl get svc
.
WebApp - Deployment et Service
webapp.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp-deployment
labels:
app: webapp
spec:
replicas: 1
selector:
matchLabels:
app: webapp
template:
metadata:
labels:
app: webapp
spec:
containers:
- name: webapp
image: nanajanashia/k8s-demo-app:v1.0
ports:
- containerPort: 3000
env:
- name: USER_NAME
valueFrom:
secretKeyRef:
name: mongo-secret
key: mongo-user
- name: USER_PWD
valueFrom:
secretKeyRef:
name: mongo-secret
key: mongo-password
- name: DB_URL
valueFrom:
configMapKeyRef:
name: mongo-config
key: mongo-url
---
apiVersion: v1
kind: Service
metadata:
name: webapp-service
spec:
type: NodePort
selector:
app: webapp
ports:
- protocol: TCP
port: 3000
targetPort: 3000
nodePort: 30100
C'est quasiment la même chose que Mongo mais en adaptant pour la Webapp.
- Nous collons tout et ajustons simplement toutes ces valeurs dans le service et le déploiement, tous les labels et sélecteurs de labels.
- Nous devons également passer les données définies dans les composants de configuration et de secret pour notre application Web et notre application de base de données MongoDB.
- Nous configurons les variables d'environnement dans un conteneur, en utilisant
valueFrom
pour référencer les secrets etconfigMaps
.
- Nous configurons également le type de service pour le rendre accessible à partir du navigateur.
- Nous créons ensuite tous ces composants dans Kubernetes en utilisant
kubectl apply
. Nous pouvons vérifier que tout fonctionne correctement en utilisantkubectl get
,kubectl describe
etkubectl logs
. - Nous pouvons également accéder à notre application web à l'aide de l'adresse IP de notre nœud de cluster et du port de service.
Les valeurs des ID seront récupéré grâce aux variables d'environnement :
env:
- name: MONGO_INITDB_ROOT_USERNAME
valueFrom:
secretKeyRef:
name: mongo-secret
key: mongo-user
- name: MONGO_INITDB_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mongo-secret
key: mongo-password
Les valeurs des variables d'environnement sont généralement fourni dans les docs ou sur le hub. On peux retrouver celles de mongoDB ici sur le hub par exemple.
Quant aux valeurs de celles-ci, pour rappel, elles sont contenu dans les [[#Mongo Secret]] :
webapp.yaml
env:
- name: USER_NAME
valueFrom:
secretKeyRef:
name: mongo-secret
key: mongo-user
- name: USER_PWD
valueFrom:
secretKeyRef:
name: mongo-secret
key: mongo-password
Additionnement, on retrouvera l'URL dans le [[#ConfigMap]] et l'ajouterons au Deployment
.
webapp.yaml
- name: DB_URL
valueFrom:
configMapKeyRef:
name: mongo-config
key: mongo-url
Rendre l'application accessible via le navigateur
Nous avons besoin de définir le port de conteneur sur 3000 et le port de service sur la même valeur. Le service sera accessible grâce au type NodePort
que nous avons setup dans le service.
NodePort
Le service NodePort
est toujours accessible à l'adresse IP du noeud du cluster, donc tous les noeuds de travail que le cluster possède. Dans notre cas, nous en avons seulement un, qui est le minikube, donc nous avons besoin de l'adresse IP du mini-cube, que nous pouvons obtenir en utilisant la commande minikube ip
ou en utilisant Kubernetes pour obtenir le noeud, qui donne également l'adresse IP du noeud.
En utilisant cette adresse IP et le port 30100, nous pouvons accéder à notre application web, qui est connectée à MongoDB. Nous avons déployé une application avec sa base de données dans Kubernetes, ce qui est une configuration de base pour la plupart des configurations d'application courantes.
apiVersion: v1
kind: Service
metadata:
name: webapp-service
spec:
type: NodePort
selector:
app: webapp
ports:
- protocol: TCP
port: 3000
targetPort: 3000
nodePort: 30100
Le grand final
Nous allons maintenant utiliser nos ressources fraichement créé. Commencez par ouvrir un Terminal.
ConfigMap et Secret doivent éxister avant les Deployments.
kubectl apply -f mongo-config.yaml
kubectl apply -f mongo-secret.yaml
kubectl apply -f mongo.yaml
kubectl apply -f webapp.yaml
Puis vérifier notre cluster.
kubectl get all
: Donne tous les composants du cluster.
kubectl get configmap
: Voir ses ConfigMap
kubectl get secret
: Voir ses Secret
Quelques commandes utiles
Commande help
Le help peut être utilisé pour les commandes et les sous commandes.
kuebctl --help
kubectl get --help
Démarrer Minikube et vérifier le statut
minikube start --vm-driver=hyperkit
minikube status
Obtenir l'adresse ip du noeud minikube
minikube ip
Obtenir des informations de base sur les composants de la k8s
kubectl get node
kubectl get pod
kubectl get svc
kubectl get all
Obtenir des informations étendues sur les composants
kubectl get pod -o wide
kubectl get node -o wide
Obtenir des informations détaillées sur un composant spécifique
kubectl describe svc {svc-name}
kubectl describe pod {pod-name}
Obtenir les journaux des applications
kubectl logs {pod-name}
Stopper le cluster Minikube
minikube stop
:::bug Troubleshooting
Problème connu - L'IP de Minikube n'est pas accessible.
Si vous ne pouvez pas accéder à la webapp du service NodePort avec
MinikubeIP:NodePort
, exécutez la commande suivante :
minikube service webapp-service :::
Liens utiles & Sources
- Installation Minikube : https://minikube.sigs.k8s.io/docs/start/
- Documentation Kubernetes : https://kubernetes.io/docs/home/
- Service : https://kubernetes.io/docs/concepts/services-networking/service/
- Mongodb image on Docker Hub: https://hub.docker.com/_/mongo
- Webapp image on Docker Hub: https://hub.docker.com/repository/docker/nanajanashia/k8s-demo-app
- k8s official documentation: https://kubernetes.io/docs/home/
- Bebapp code repo: https://gitlab.com/nanuchi/developing-with-docker/-/tree/feature/k8s-in-hour
- Exercice basé sur Kubernetes in one hours
- Associated gitlab examples